package game.editer;

import game.editer.data.CopyData;
import game.editer.data.SettingData;
import game.editer.config.SettingConfig;
import game.editer.history.AddEffect;
import game.editer.history.RemoveEffect;
import game.editer.history.ChangeAttr;
import game.editer.ui.KeyInput.KeyDisplay;
import game.editer.ui.BaseAttributeInput;
import game.editer.view.AtlasOffestEditerView;
import game.editer.core.ExportABProject;
import haxe.Exception;
import hx.assets.XmlAtlas;
import game.assets.Hxwz2RolePackageFuture;
import game.utils.XmlTools;
import game.data.ActionData;
import game.utils.UpdateCore;
import game.utils.ProjectTools;
import game.editer.view.AlertView;
import game.editer.config.RoleDataConfig;
import game.editer.view.InputListDataView;
import game.assets.RoleAssets;
import game.editer.view.CreateEffectPreviewView;
import hx.utils.KeyboardTools;
import game.editer.data.PackageBuildData;
import game.utils.FileSystem;
#if electron
import electron.renderer.IpcRenderer;
import sys.io.File;
#end
import game.data.ProjectDataExport;
import game.editer.history.HistoryData;
import hx.display.InputLabel;
import game.editer.config.EffectConfig;
import hx.display.DisplayObjectContainer;
import game.worlds.GameEffect;
import hx.display.DisplayObject;
import game.editer.config.FrameConfig;
import hx.events.Keyboard;
import hx.events.KeyboardEvent;
import haxe.io.Path;
import game.worlds.GameWorld;
import game.worlds.GameRole;
import game.assets.ABProjFuture;
import game.assets.HxwzAssets;
import hx.display.Sprite;
import hx.geom.Point;
import hx.events.MouseEvent;
import hx.utils.ScaleUtils;
import game.shader.RepeatTextureShader;
import hx.ui.UIManager;
import hx.display.OpenFlBitmap;
import hx.events.Event;
import hx.display.Quad;
import hx.display.UILoadScene;
import hx.layout.AnchorLayoutData;
import hx.layout.AnchorLayout;

using haxe.io.Path;

/**
 * 编辑器舞台
 */
@:build(hx.macro.UIBuilder.build("editerAssets/views/EditerMain.xml"))
class EditerStage extends UILoadScene {
	public var lineX:Quad;

	public var lineY:Quad;

	public var gird:OpenFlBitmap;

	public static var current:EditerStage;

	public static var world:EditerWorld;

	/**
	 * 时间轴
	 */
	public static var timeline:TimelineEditer;

	/**
	 * 属性
	 */
	public static var attribute:AttrEditer;

	/**
	 * 主菜单
	 */
	public static var mainMenu:MainMenu;

	/**
	 * 对象选择器
	 */
	public static var objectSelect:ObjectSelectEditer;

	/**
	 * 精灵图选择器
	 */
	public static var spriteEditer:SpritePoolEditer;

	/**
	 * 图层选择器
	 */
	public static var layerEditer:LayerEditer;

	/**
	 * 工具箱
	 */
	public static var toolPanel:ToolPanel;

	/**
	 * 历史操作数据记录
	 */
	public static var historyData:HistoryData = new HistoryData();

	/**
	 * 动作面板
	 */
	public static var actionPlane:ActionPlane;

	override function onLoaded() {
		super.onLoaded();

		current = this;

		this.topView.layout = new AnchorLayout();

		// 背景渲染器
		gird = new OpenFlBitmap(UIManager.getBitmapData("img_gird_bg"));
		gird.bitmap.shader = RepeatTextureShader.getInstance();
		gird.width = 2048 * 4;
		gird.height = 2048 * 4;
		gird.x = -gird.width / 2;
		gird.y = -gird.height / 2;
		this.boxStage.addChild(gird);

		lineX = new Quad(1, 100, 0x0);
		this.boxStage.addChild(lineX);
		lineY = new Quad(100, 1, 0x0);
		this.boxStage.addChild(lineY);

		world = new EditerWorld();
		this.boxStage.addChild(world);

		objectSelect = new ObjectSelectEditer();
		this.boxStage.addChild(objectSelect);

		attribute = new AttrEditer();
		attribute.width = 245;

		timeline = new TimelineEditer();
		timeline.layoutData = new AnchorLayoutData(null, attribute.width, 0, 0);
		this.topView.addChild(timeline);
		timeline.addEventListener(Event.CHANGE, onTimelineChange);
		this.boxStage.x = stage.stageWidth / 2;
		this.boxStage.y = stage.stageHeight / 2;

		// 图层
		layerEditer = new LayerEditer();
		layerEditer.height = timeline.height;
		layerEditer.width = attribute.width;
		layerEditer.layoutData = new AnchorLayoutData(null, 0, 0, null);
		this.topView.addChild(layerEditer);

		var fps = new hx.display.FPS();
		this.topView.addChild(fps);
		fps.layoutData = new AnchorLayoutData(null, null, timeline.height, 240);
		fps.scaleX = fps.scaleY = 0.6;

		mainMenu = new MainMenu();
		mainMenu.height = 35;
		mainMenu.layoutData = new AnchorLayoutData(0, 0, null, 0);
		this.topView.addChild(mainMenu);

		attribute.layoutData = new AnchorLayoutData(35, 0, timeline.height, null);
		this.topView.addChild(attribute);

		actionPlane = new ActionPlane();
		this.topView.addChild(actionPlane);
		actionPlane.width = attribute.width;
		actionPlane.layoutData = new AnchorLayoutData(35, attribute.width, timeline.height, null);

		spriteEditer = new SpritePoolEditer();
		spriteEditer.width = 240;
		spriteEditer.layoutData = new AnchorLayoutData(35, null, timeline.height, null);
		this.topView.addChild(spriteEditer);

		toolPanel = new ToolPanel();
		this.topView.addChild(toolPanel);
		toolPanel.layoutData = AnchorLayoutData.topLeft(35 + 8, spriteEditer.width + 8);

		this.stage.addEventListener(Event.RESIZE, onWindowResize);
		this.onWindowResize(null);

		this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
		this.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		stage.addEventListener(MouseEvent.CLICK, onMouseClick);
		stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
		this.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);

		stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
		stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);

		#if electron
		IpcRenderer.on("save", () -> {
			this.saveProject();
		});
		IpcRenderer.on("about", () -> {
			// 关于
			var view = new AboutTipsView("关于", 600, 400);
			this.topView.addChild(view);
		});
		IpcRenderer.on("open-project", () -> {
			// 打开项目
			FileSystem.openFile({
				filters: [
					{
						name: "*.abproj",
						extensions: ["abproj"]
					}
				]
			}, (path:FileEvent) -> {
				EditerStage.current.openABProject(path.filePaths[0]);
			});
		});
		IpcRenderer.on("new-project", () -> {
			FileSystem.saveFile(function(fileEvent:SaveFileEvent) {
				var abfile = ProjectTools.createProject(fileEvent.filePath);
				openABProject(abfile);
			});
		});
		IpcRenderer.on("role-build", () -> {
			// 打包项目
			saveProject(false);
		});
		IpcRenderer.on("role-build-preview", () -> {
			var buildData = saveProject(false);
			// 构造完成后，进行预览
			if (buildData != null)
				IpcRenderer.send("runtime-preview", buildData.getOutputPath());
		});
		// 添加特效
		IpcRenderer.on("add-effect", () -> {
			// 打包项目
			var view = new CreateEffectPreviewView("创建新的特效", 800, 600);
			this.topView.addChild(view);
			view.onCreateEffect = (effect) -> {
				if (EditerStage.timeline.currentFrameData != null) {
					EditerStage.timeline.currentFrameData.addEffect(effect);
					EditerStage.timeline.updateTimelineData(true);
					EditerStage.historyData.todo(new AddEffect(EditerStage.timeline.currentFrameData, effect));
				}
			}
		});
		// 编辑人物属性
		IpcRenderer.on("edit-character", () -> {
			var view = new InputListDataView("编辑人物属性", RoleDataConfig.ATTRIBUTES);
			view.data = roleAssets.data.attrData;
			view.height = 600;
			view.show();
			view.addEventListener(AlertView.BUTTON_CLICK, (e:Event) -> {
				if (e.data == "确定") {
					view.done();
				}
			});
		});
		// 更新版本
		IpcRenderer.on("check-update", () -> {
			new UpdateCore((code) -> {
				if (code == 0) {
					AlertView.showView("更新完成", "请重启编辑器应用", (tag) -> {
						IpcRenderer.send("relunch");
					});
				} else {
					AlertView.showView("更新失败", "请检查网络或者在Gitee中提出问题，错误码：" + code);
				}
			});
		});
		// 初始化动作
		IpcRenderer.on("role-init-action", () -> {
			if (roleAssets == null) {
				return;
			}
			var actions = [
				"待机", "跑步", "跳跃", "下降", "落地", "降落", "打飞", "倒落", "受伤", "防御", "起身", "普通攻击", "空中攻击", "瞬步"
			];
			for (key in actions) {
				if (!roleAssets.data.actions.exists(key)) {
					var action = new ActionData();
					action.name = key;
					timeline.addActionData(action);
				}
			}
		});
		// 精灵图去重
		IpcRenderer.on("atlas-delete-duplicate", () -> {
			if (roleAssets == null) {
				return;
			}
			FileSystem.openFile({
				filters: [
					{
						name: "*.xml",
						extensions: ["xml"]
					}
				]
			}, (path:FileEvent) -> {
				var xml = XmlTools.removeDuplicateNodes(Xml.parse(File.getContent(path.filePaths[0])));
				File.saveContent(path.filePaths[0], xml.toString());
			});
		});
		// 旧版本转换
		IpcRenderer.on("role-old-version-convert", () -> {
			FileSystem.openFile({
				filters: [
					{
						name: "*.data",
						extensions: ["data"]
					}
				]
			}, (path:FileEvent) -> {
				// 导出资源项目
				trace("开始转换项目：", path.filePaths[0]);
				ExportABProject.export(path.filePaths[0], (error, path) -> {
					if (error != null) {
						AlertView.showView("转换失败", error);
					} else {
						AlertView.showView("转换成功", "项目已经转换至" + path);
					}
				});
			});
		});
		// 旧版本XML格式转换
		IpcRenderer.on("role-old-version-convert-xml", () -> {
			FileSystem.openFile({
				filters: [
					{
						name: "*.xml",
						extensions: ["xml"]
					}
				]
			}, (path:FileEvent) -> {
				// 导出资源项目
				trace("开始转换项目：", path.filePaths[0]);
				ExportABProject.exportByXml(path.filePaths[0], (error, path) -> {
					if (error != null) {
						AlertView.showView("转换失败", error);
					} else {
						AlertView.showView("转换成功", "项目已经转换至" + path);
					}
				});
			});
		});
		IpcRenderer.on("clone-frame", (e) -> {
			if (timeline.currentFrameData != null) {
				var frame = timeline.currentFrameData.clone();
				timeline.insertFrame(frame);
			}
		});
		IpcRenderer.on("blank-frame", (e) -> {
			if (timeline.currentFrameData != null) {
				var frame = timeline.currentFrameData.clone();
				frame.name = "";
				timeline.insertFrame(frame);
			}
		});
		IpcRenderer.on("edit-effect-anchor", (e) -> {
			if (roleAssets != null) {
				var view = new CreateEffectPreviewView("选择编辑锚点的特效", 900, 800);
				this.topView.addChild(view);
				view.onCreateEffect = (effectData) -> {
					var view = new AtlasOffestEditerView("精灵图属性编辑", 800, 700);
					view.edit(effectData.name);
					this.topView.addChild(view);
				}
			}
		});
		// 位移缩放
		IpcRenderer.on("timeline-move-scale", (e) -> {
			if (timeline.currentActionData != null) {
				var view = new InputListDataView("时间轴位移缩放", [
					{
						{
							text: "缩放系数",
							key: "scale",
							type: Number,
							defalutValue: 1
						}
					}
				]);
				view.data = {};
				view.addEventListener(AlertView.BUTTON_CLICK, (e:Event) -> {
					if (e.data == "确定") {
						view.done();
						for (frame in timeline.currentActionData.frames) {
							if (frame.originMoveX != null)
								frame.originMoveX *= view.data.scale;
							if (frame.originMoveY != null)
								frame.originMoveY *= view.data.scale;
						}
						timeline.currentActionData.updateActionData();
						timeline.updateTimelineData(true);
					}
				});
				view.show();
			}
		});
		// 初始化代码
		IpcRenderer.on("role-init-code", (e) -> {
			if (roleAssets != null) {
				ProjectTools.createHaxeProject(projectPath);
			} else {
				AlertView.showView("提示", "需要打开项目后使用");
			}
		});
		// 初始化出招表
		IpcRenderer.on("role-init-action-table", (e) -> {
			if (roleAssets != null) {
				// ProjectTools.createActionTable(projectPath);
			} else {
				AlertView.showView("提示", "需要打开项目后使用");
			}
		});
		// 撤销
		IpcRenderer.on("undo", (e) -> {
			trace("撤销");
			historyData.undo();
		});
		// 添加位移帧
		IpcRenderer.on("add-move-frame", (e) -> {
			var oldAttr = {
				originMoveX: timeline.currentFrameData.originMoveX,
				originMoveY: timeline.currentFrameData.originMoveY
			}
			var newAttr = {
				originMoveX: @:privateAccess timeline.currentFrameData._originMoveX,
				originMoveY: @:privateAccess timeline.currentFrameData._originMoveY
			}
			historyData.todo(new ChangeAttr(timeline.currentFrameData, oldAttr, newAttr));
			timeline.currentFrameData.originMoveX = @:privateAccess timeline.currentFrameData._originMoveX;
			timeline.currentFrameData.originMoveY = @:privateAccess timeline.currentFrameData._originMoveY;
			timeline.updateTimelineData(true);
		});
		// 添加旋转帧
		IpcRenderer.on("add-rotate-frame", (e) -> {
			var oldAttr = {
				originRotate: timeline.currentFrameData.originRotate
			}
			var newAttr = {
				originRotate: @:privateAccess timeline.currentFrameData._originRotate
			}
			historyData.todo(new ChangeAttr(timeline.currentFrameData, oldAttr, newAttr));
			timeline.currentFrameData.originRotate = @:privateAccess timeline.currentFrameData._originRotate;
			timeline.updateTimelineData(true);
		});
		// 添加缩放帧
		IpcRenderer.on("add-scale-frame", (e) -> {
			var oldAttr = {
				originScaleX: timeline.currentFrameData.originScaleX,
				originScaleY: timeline.currentFrameData.originScaleY
			}
			var newAttr = {
				originScaleX: @:privateAccess timeline.currentFrameData._originScaleX,
				originScaleY: @:privateAccess timeline.currentFrameData._originScaleY
			}
			historyData.todo(new ChangeAttr(timeline.currentFrameData, oldAttr, newAttr));
			timeline.currentFrameData.originScaleX = @:privateAccess timeline.currentFrameData._originScaleX;
			timeline.currentFrameData.originScaleY = @:privateAccess timeline.currentFrameData._originScaleY;
			timeline.updateTimelineData(true);
		});
		// 添加透明度帧
		IpcRenderer.on("add-alpha-frame", (e) -> {
			var oldAttr = {
				originAlpha: timeline.currentFrameData.alpha
			}
			var newAttr = {
				originAlpha: @:privateAccess timeline.currentFrameData._originAlpha
			}
			historyData.todo(new ChangeAttr(timeline.currentFrameData, oldAttr, newAttr));
			timeline.currentFrameData.originAlpha = @:privateAccess timeline.currentFrameData._originAlpha;
			timeline.updateTimelineData(true);
		});
		// 打开设置
		IpcRenderer.on("settings", (e) -> {
			var view = new InputListDataView("设置", SettingConfig.ATTRIBUTES);
			view.data = SettingData.config;
			view.buttons = ["取消", "确定"];
			view.show();
			view.addEventListener(AlertView.BUTTON_CLICK, (e:Event) -> {
				if (e.data == "确定") {
					view.done();
					SettingData.save();
				}
			});
		});
		// 复制与粘贴
		IpcRenderer.on("copy", (e) -> {
			// 复制
			if (timeline.currentFrameData != null) {
				var frameData = CopyData.copy(timeline.currentFrameData);
				trace("复制成功", frameData);
			}
		});

		IpcRenderer.on("paste", (e) -> {
			// 粘贴
		});
		#end
	}

	private function onKeyDown(e:KeyboardEvent):Void {}

	/**
	 * 获得当前弹窗显示的窗口
	 */
	public var currentShowBaseView(get, never):BaseView;

	private function get_currentShowBaseView():BaseView {
		var i = topView.children.length;
		while (i-- > 0) {
			var view = topView.children[i];
			if (view is BaseView) {
				return cast view;
			}
		}
		return null;
	}

	private function onKeyUp(e:KeyboardEvent):Void {
		if (stage.focus is InputLabel) {
			return;
		}
		if (stage.focus is KeyDisplay) {
			return;
		}
		if (currentShowBaseView != null)
			return;
		if (timeline.currentActionData == null)
			return;
		var code = e.keyCode;
		switch (code) {
			case Keyboard.BACKSPACE:
				// 删除
				var isRemoved = false;
				var timelineFrame:TimelineFrame = cast timeline.timelineListView.getChildAt(timeline.currentFrame);
				if (timelineFrame != null) {
					var cur = timeline.currentFrame;
					if (timelineFrame.quad.colorTransform != null) {
						// 全部删除
						timeline.removeFrame(timeline.currentFrameData);
						isRemoved = true;
					} else {
						// 删除指定属性
						for (quad in timelineFrame.otherFrames) {
							if (quad.colorTransform != null) {
								switch quad.name {
									case "特效":
										// 删除所有特效
										var oldData = {
											effects: timeline.currentFrameData.effects
										}
										var newData = {
											effects: []
										}
										historyData.todo(new ChangeAttr(timeline.currentFrameData, oldData, newData));
										timeline.currentFrameData.effects = [];
										isRemoved = true;
									case "停顿":
										// 删除所有停顿
										var oldData = {
											isStop: timeline.currentFrameData.isStop
										}
										var newData = {
											isStop: false
										}
										historyData.todo(new ChangeAttr(timeline.currentFrameData, oldData, newData));
										timeline.currentFrameData.isStop = false;
										isRemoved = true;
									case "位移":
										var oldData = {
											originMoveX: timeline.currentFrameData.originMoveX,
											originMoveY: timeline.currentFrameData.originMoveY
										}
										var newData = {
											originMoveX: null,
											originMoveY: null
										}
										historyData.todo(new ChangeAttr(timeline.currentFrameData, oldData, newData));
										timeline.currentFrameData.originMoveX = null;
										timeline.currentFrameData.originMoveY = null;
										isRemoved = true;
									case "缩放":
										var oldData = {
											originScaleX: timeline.currentFrameData.originScaleX,
											originScaleY: timeline.currentFrameData.originScaleY
										}
										var newData = {
											originScaleX: null,
											originScaleY: null
										}
										historyData.todo(new ChangeAttr(timeline.currentFrameData, oldData, newData));
										timeline.currentFrameData.originScaleX = null;
										timeline.currentFrameData.originScaleY = null;
										isRemoved = true;
									case "旋转":
										var oldData = {
											originRotate: timeline.currentFrameData.originRotate
										}
										var newData = {
											originRotate: null
										}
										historyData.todo(new ChangeAttr(timeline.currentFrameData, oldData, newData));
										timeline.currentFrameData.originRotate = null;
										isRemoved = true;
									case "透明":
										var oldData = {
											originAlpha: timeline.currentFrameData.originAlpha
										}
										var newData = {
											originAlpha: null
										}
										historyData.todo(new ChangeAttr(timeline.currentFrameData, oldData, newData));
										timeline.currentFrameData.originAlpha = null;
										isRemoved = true;
									case "音频":
										var oldData = {
											sound: timeline.currentFrameData.sound
										}
										var newData = {
											sound: null
										}
										historyData.todo(new ChangeAttr(timeline.currentFrameData, oldData, newData));
										timeline.currentFrameData.sound = null;
										isRemoved = true;
									case "事件":
										var oldData = {
											eventTag: timeline.currentFrameData.eventTag
										}
										var newData = {
											eventTag: null
										}
										historyData.todo(new ChangeAttr(timeline.currentFrameData, oldData, newData));
										timeline.currentFrameData.eventTag = null;
										isRemoved = true;
									case "碰撞":
										var oldData = {
											collision: timeline.currentFrameData.collision
										}
										var newData = {
											collision: null
										}
										historyData.todo(new ChangeAttr(timeline.currentFrameData, oldData, newData));
										timeline.currentFrameData.collision = null;
										isRemoved = true;
								}
							}
						}
					}
					if (!isRemoved && objectSelect.visible) {
						if (objectSelect.selectedDisplay is GameEffect) {
							var effect:GameEffect = cast objectSelect.selectedDisplay;
							historyData.todo(new RemoveEffect(effect.originData.frameData, effect.originData));
							effect.originData.frameData.removeEffect(effect.originData);
							timeline.updateTimelineData(true);
							objectSelect.visible = false;
						}
					}
					if (isRemoved) {
						timeline.currentActionData.updateActionData();
						timeline.updateTimelineData();
						cur = Std.int(Math.min(timeline.currentActionData.frames.length, cur));
						world.role.updateMovieClipActionData(timeline.currentActionData.name);
						timeline.currentFrame = cur;
					}
				}
			case Keyboard.EQUAL:
				// 下一帧
				timeline.nextFrame();
			case Keyboard.MINUS:
				// 上一帧
				timeline.prevFrame();
		}
	}

	private function onTimelineChange(e:Event):Void {
		if (timeline.currentActionData == null || timeline.isPreview) {
			return;
		}
		@:privateAccess world.role.__currentSkillActionName = timeline.currentActionData.name;
		world.role.x = world.role.y = 0;
		world.role.playAndStop(timeline.currentActionData.name, timeline.currentFrame);
		@:privateAccess world.role.__currentSkillActionName = null;
		// 绑定属性
		attribute.bindEditData("帧属性", timeline.currentFrameData, FrameConfig.ATTRIBUTES);
	}

	private var __isDown = false;

	private var __lastStagePoint:Point = new Point();

	private function onMouseClick(e:MouseEvent):Void {
		if (e.isCtrlOrCommand)
			return;
		if (e.target is GameRole || e.target is GameEffect) {
			var display:DisplayObjectContainer = e.target;
			var rect = display.getBounds(display.parent);
			objectSelect.width = rect.width;
			objectSelect.height = rect.height;
			objectSelect.x = rect.x;
			objectSelect.y = rect.y;
			objectSelect.visible = true;
			objectSelect.selectedDisplay = display;
			// 如果是特效，则显示特效属性面板
			if (e.target is GameEffect) {
				var effect:GameEffect = e.target;
				#if editer
				attribute.bindEditData("特效属性", effect.originData, EffectConfig.ATTRIBUTES);
				#end
			}
			// 时间轴取消所有选中状态
			timeline.cannelFrameSelect();
		} else if (!(e.target is hx.display.Stage || isTouchTools(e.target))) {
			// 排除舞台、工具对象
			objectSelect.visible = false;
			objectSelect.selectedDisplay = null;
			attribute.bindEditData("帧属性", timeline.currentFrameData, FrameConfig.ATTRIBUTES);
		}
	}

	public function isTouchTools(target:DisplayObject):Bool {
		return target is ObjectSelectTools || target.parent is ObjectSelectTools;
	}

	private function onMouseDown(e:MouseEvent):Void {
		if (isTouchTools(e.target)) {
			var pos = boxStage.globalToLocal(new Point(e.stageX, e.stageY));
			objectSelect.currentEditTools.onBeginMouse(pos.x, pos.y);
			return;
		}
		__isDown = true;
		__lastStagePoint.x = e.stageX;
		__lastStagePoint.y = e.stageY;
	}

	private function onMouseMove(e:MouseEvent):Void {
		if (e.isCtrlOrCommand)
			return;
		if (objectSelect.currentEditTools.isBegin) {
			var pos = boxStage.globalToLocal(new Point(e.stageX, e.stageY));
			objectSelect.currentEditTools.onMoveMouse(pos.x, pos.y);
			return;
		}
		if (__isDown) {
			this.boxStage.x += e.stageX - __lastStagePoint.x;
			this.boxStage.y += e.stageY - __lastStagePoint.y;
			__lastStagePoint.x = e.stageX;
			__lastStagePoint.y = e.stageY;
		}
	}

	private function onMouseUp(e:MouseEvent):Void {
		__isDown = false;
		if (objectSelect.currentEditTools.isBegin) {
			var pos = boxStage.globalToLocal(new Point(e.stageX, e.stageY));
			objectSelect.currentEditTools.onEndMouse(pos.x, pos.y);
			return;
		}
	}

	private function onMouseWheel(e:MouseEvent):Void {
		// var s = e.delta > 0 ? 1.01 : 0.99;
		var s = 1 + e.delta * 0.0001;
		var minScale = Math.max(gird.width / stage.stageWidth, gird.height / stage.stageHeight);
		var maxScale = Math.max(stage.stageWidth / gird.width, stage.stageHeight / gird.height);

		var m = this.boxStage.transform.clone();
		var pos = boxStage.parent.globalToLocal(new Point(e.stageX, e.stageY));
		m.translate(-pos.x, -pos.y);
		m.scale(s, s);
		m.translate(pos.x, pos.y);
		this.boxStage.transform = m;

		if (this.boxStage.scaleX > minScale) {
			this.boxStage.scaleX = this.boxStage.scaleY = minScale;
		} else if (this.boxStage.scaleX < maxScale) {
			this.boxStage.scaleX = this.boxStage.scaleY = maxScale;
		}
		this.onWindowResize(null);
	}

	private function onWindowResize(e:Event):Void {
		lineX.height = 20480;
		lineY.width = 20480;
		// var s = Math.max(1, 1 / this.boxStage.scaleX);
		var s = 1 / this.boxStage.scaleX;
		s = Math.max(1, s);
		lineX.scaleX = s;
		lineY.scaleY = s;
		lineX.x = -lineX.width / 2;
		lineX.y = -lineX.height / 2;
		lineY.x = -lineY.width / 2;
		lineY.y = -lineY.height / 2;
	}

	public static var assets:HxwzAssets;

	public static var projectPath:String;

	public static var projectImagesPath(get, never):String;

	public static var projectSoundPath(get, never):String;

	private static function get_projectSoundPath():String {
		return Path.join([Path.directory(projectPath), "sound"]);
	}

	private static function get_projectImagesPath():String {
		return Path.join([Path.directory(projectPath), "images"]);
	}

	/**
	 * 角色资源
	 */
	public static var roleAssets(get, never):RoleAssets;

	private static function get_roleAssets():RoleAssets {
		if (assets == null)
			return null;
		var roleData = assets.roles.get(Path.withoutExtension(Path.withoutDirectory(projectPath)));
		return roleData;
	}

	/**
	 * 加载abproj人物资源
	 * @param path 
	 */
	public function openABProject(path:String):Void {
		if (path == null)
			return;
		projectPath = path;
		assets = new HxwzAssets();
		assets.pushFuture(new ABProjFuture(path));
		assets.onComplete((a) -> {
			world.displayBox.removeChildren();
			var roleData = assets.roles.get(Path.withoutExtension(Path.withoutDirectory(path)));
			var role = new GameRole(world, roleData);
			world.role = role;
			world.addDisplay(role);
			role.play("待机");
			// 设置时间轴编辑数据
			timeline.projectData = roleData.data;
			// 设置精灵图库数据
			spriteEditer.projectData = roleData.data;
			// 设置动作列表数据
			actionPlane.projectData = roleData.data;
			// 标题变更
			IpcRenderer.send("change-title", path);
		});
		assets.onError((err) -> {
			trace("打开人物工程失败", err);
			AlertView.showView("打开人物工程失败", err.error + "(" + err.errorCode + ")");
		});
		assets.start();
		KeyboardTools.reset();
	}

	/**
	 * 保存abproj项目
	 */
	public function saveProject(forceSave:Bool = true):PackageBuildData {
		#if (electron)
		if (assets == null) {
			return null;
		}
		var exportData = new ProjectDataExport(world.role.assets.data);
		var data = exportData.export();
		if (forceSave) {
			File.saveContent(projectPath, data);
		}
		var buildData = new PackageBuildData(projectPath);
		buildData.build((f) -> {
			trace("构造进度：", f);
		}, data);
		return buildData;
		#else
		return null;
		#end
	}
}
